package sketch.seg.cd.exp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import sketch.seg.cd.CDStaticKH;
import sketch.seg.cd.exp.CDRhoStat.Data;

public class CDExp {

	public static final int MIN_K = 1;
	public static final int MAX_K = 21;

	public static final double SCALE = 2;

	public static double[]
	                     MIN_H = new double[MAX_K],
	                     MAX_H = new double[MAX_K];
//	private CDTemplate template;

	private int K1, K2;

	private double H1, H2;

	private double precision1, recall1;

	private double precision2, recall2;

	public double getPrecision2() {
		return precision2;
	}

	public void setPrecision2(double precision2) {
		this.precision2 = precision2;
	}

	public double getRecall2() {
		return recall2;
	}

	public void setRecall2(double recall2) {
		this.recall2 = recall2;
	}

	public double getPrecision1() {
		return precision1;
	}

	public void setPrecision1(double precision1) {
		this.precision1 = precision1;
	}

	public double getRecall1() {
		return recall1;
	}

	public void setRecall1(double recall1) {
		this.recall1 = recall1;
	}

	public CDExp(File file) {
		CDTemplate.get().readFromFile(file);
		init();
	}

	public CDExp(File[] files) {
		CDTemplate.get().readFromFiles(files);
		init();
	}

	public CDExp(String[] filenames) {
		CDTemplate.get().readFromFiles(filenames);
		init();
	}

	private void init() {
		setK1(0);
		setH1(0);
		setK2(0);
		setH2(0);
		findRhoKStat();
	}

	public void find1() {
//		double max_rec = 0;

//		System.out.print("calculating, please wait ");
		for (int K = MIN_K; K < MAX_K; K++) {
//			System.out.print(".");
			for (double H = MIN_H[K]; H < MAX_H[K]; H += 0.1) {

				CDStaticKH cd = new CDStaticKH();
				cd.setK1(K);
				cd.setH1(H);
				cd.setSingleStep(true);
				CDTemplate.get().cd(cd);

				double pre = CDTemplate.get()._d_of_precision();
				double rec = CDTemplate.get()._d_of_recall();

//				System.out.printf("K=%d,H=%1.2f", K, H);
//				System.out.println(
//						":precision(" + pre + ")" +
//						":recall(" + rec + ")");


				if (calc(pre, rec) > calc(getPrecision1(), getRecall1())) {
					setRecall1(rec);
					setPrecision1(pre);
					setK1(K);
					setH1(H);
				}

			}
		}
//		System.out.println();
	}

	private double calc(double major, double minor) {
		return major * SCALE + minor;
	}

	public void find2() {

		if (getK1() == 0)
			find1();

		for (int K = getK1() + 1; K < MAX_K; K++) {

			for (double H = MIN_H[K]; H < MAX_H[K]; H += 0.1) {

				CDStaticKH cd = new CDStaticKH();
				cd.setK1(getK1());
				cd.setH1(getH1());
				cd.setK2(K);
				cd.setH2(H);
				cd.setSingleStep(false);

				CDTemplate.get().cd(cd);

				double pre = CDTemplate.get()._d_of_precision();
				double rec = CDTemplate.get()._d_of_recall();

//				System.out.printf("K=%d,H=%1.2f", K, H);
//				System.out.println(
//						":precision(" + pre + ")" +
//						":recall(" + rec + ")");

				if (calc(rec, pre) > calc(getRecall2(), getPrecision2())) {
					setRecall2(rec);
					setPrecision2(pre);
					setK2(K);
					setH2(H);
				}
			}
		}
	}

	public void print1() {
		System.out.printf("Single Step: K = %d, H = %1.2f, pre = %1.2f, rec = %1.2f\n",
				getK1(), getH1(), getPrecision1(), getRecall1());
	}

	public void print2() {
		System.out.printf("Multi Step: K1 = %d, H1 = %1.3f, K2 = %d, H2 = %1.3f\n" +
				"            precision = %1.3f, recall = %1.3f\n",
				getK1(), getH1(), getK2(), getH2(), getPrecision2(), getRecall2());
	}

	public int getK1() {
		return K1;
	}

	public void setK1(int k1) {
		K1 = k1;
	}

	public int getK2() {
		return K2;
	}

	public void setK2(int k2) {
		K2 = k2;
	}

	public double getH1() {
		return H1;
	}

	public void setH1(double h1) {
		H1 = h1;
	}

	public double getH2() {
		return H2;
	}

	public void setH2(double h2) {
		H2 = h2;
	}

	public boolean equals(double d1, double d2) {
		return Math.abs(d1 - d2) < 0.000000001;
	}

	public static void main(String[] args) {
		Properties p = new Properties();
		try {
			p.load(new FileInputStream("src/sketch/seg/cd/exp/file.properties"));
		} catch (Exception e) {
			e.printStackTrace();
		}

		String dir = p.getProperty("dir");
		String files = p.getProperty("files");
		String fs[] = files.split(" ");
		File fss[] = new File[fs.length];
		for (int i = 0; i < fss.length; i ++) {
			fss[i] = new File(dir + fs[i]);
		}
		System.out.println("sample files: ");
		for (int i = 0; i < fs.length; i++) {
			System.out.println("\t" + dir + fs[i]);
		}
		CDExp exp = new CDExp(fss);

		exp.find1();
		exp.print1();

		exp.find2();
		exp.print2();
	}

	public void findRhoKStat() {
		CDRhoStat stat = new CDRhoStat();

		CDStaticKH cd = new CDStaticKH();
		for (int i = MIN_K; i < MAX_K; i++) {
			cd.setK1(i);
			cd.setSingleStep(true);
			CDTemplate.get().cd(cd);

			stat.addData(new Data(i, cd.getRhos()));

			MIN_H[i] = stat.getMinRhoByK(i);
			MAX_H[i] = stat.getMaxRhoByK(i);

			System.out.printf("%d\t%1.2f\n", i, MAX_H[i]);
		}

	}


}
